package com.spark.lola.controller.logistics;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.spark.lola.logistics.constant.LogisticsConstant;
import com.spark.lola.logistics.entity.OrderInfo;
import com.spark.lola.logistics.entity.OrderProcess;
import com.spark.lola.logistics.mapper.LogisticsOrderInfoMapper;
import com.spark.lola.logistics.mapper.LogisticsOrderProcessMapper;
import com.spark.lola.logistics.service.DriverInfoService;
import com.spark.lola.logistics.service.LogisticsOrderInfoService;
import com.spark.lola.logistics.vo.OrderCompleteVo;
import com.spark.lola.logistics.vo.OrderInfoVo;
import com.spark.lola.statistics.entity.StatisticsCar;
import com.spark.lola.support.common.entity.ShiroUser;
import com.spark.lola.support.common.util.ResponseBean;
import com.spark.lola.support.common.util.TimeUtil;
import com.spark.lola.support.core.param.ExcelParams;
import com.spark.lola.support.mvc.service.ExcelServiceImpl;
import com.spark.lola.support.mybatis.common.QueryCondition;
import com.spark.lola.support.mybatis.controller.BaseController;
import com.spark.lola.support.mybatis.entity.PageParam;
import com.spark.lola.support.mybatis.entity.QueryParam;
import com.spark.lola.support.wms.configuration.WmsProperties;
import com.spark.lola.support.wms.constant.KafkaTopic;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author: Zhi-peng wang
 * @date: 2020/04/27 16:45
 * 货运单信息接口
 **/
@RestController
@RequestMapping("/api/logistics/order")
@Api(value = "/api/logistics/order", tags = "货运单信息接口")
public class LogisticsOrderInfoController extends BaseController {

    private static final Logger logger = LoggerFactory.getLogger(LogisticsOrderInfoController.class);

    @Autowired
    private LogisticsOrderInfoService logisticsOrderInfoService;

    @Autowired
    private DriverInfoService driverInfoService;

    @Autowired
    private WmsProperties wmsProperties;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Autowired
    private LogisticsOrderInfoMapper logisticsOrderInfoMapper;

    @Autowired
    private LogisticsOrderProcessMapper logisticsOrderProcessMapper;

    @Autowired
    private ExcelServiceImpl excelService;

    @ApiOperation(value = "分页查询货运单信息")
    @RequiresPermissions(value = "m5140")
    @RequestMapping(value = "/findBy", method = RequestMethod.POST)
    public ResponseBean findPage(@RequestBody QueryParam<OrderInfoVo> queryParam, @SessionAttribute ShiroUser shiroUser) {
        // 当前管理员是否货运业务岗位
        if (wmsProperties.getLogistics().getDutyId().get(1).equals(shiroUser.getDutyId())) {
            QueryCondition queryCondition = new QueryCondition();
            queryCondition.setKey("o.creatorId");
            queryCondition.setOper("=");
            queryCondition.setValue(shiroUser.getId());
            queryParam.getQueryList().add(queryCondition);
        }
        // 当前管理员是否隶属货运部 并管理指定用户
        if (!StringUtils.isEmpty(shiroUser.getControlUsers()) && wmsProperties.getLogistics().getDeptId().equals(shiroUser.getDeptId())) {
            // 绑定指定用户链
            bindControlQuery(queryParam, shiroUser, "o.creatorId", false);
        }
        IPage<OrderInfoVo> orderInfoVoIPage = logisticsOrderInfoService.findPage(queryParam);
        return ResponseBean.success(orderInfoVoIPage);
    }

    @ApiOperation(value = "获取货运单信息详情")
    @ApiImplicitParam(name = "id", value = "货运单信息id", required = true, dataType = "long", paramType = "path")
    @RequiresPermissions(value = "m5144")
    @RequestMapping(value = "/findInfo/{id}", method = RequestMethod.GET)
    public ResponseBean findInfo(@PathVariable long id, @SessionAttribute ShiroUser shiroUser) throws Exception {
        OrderInfo orderInfo = new OrderInfo();
        if (id != 0) {
            orderInfo = logisticsOrderInfoService.findInfo(id);
        } else {
            orderInfo.setCarId(driverInfoService.findCarId(shiroUser.getId()));
        }
        return ResponseBean.success(orderInfo);
    }

    @ApiOperation(value = "获取货运单信息详情")
    @ApiImplicitParam(name = "id", value = "货运单信息id", required = true, dataType = "long", paramType = "path")
    @RequestMapping(value = "/findReturnInfo/{id}", method = RequestMethod.GET)
    public ResponseBean findReturnInfo(@PathVariable long id, @SessionAttribute ShiroUser shiroUser) throws Exception {
        return ResponseBean.success(logisticsOrderInfoService.findInfo(id));
    }

    @ApiOperation(value = "添加/修改货运单信息")
    @RequiresPermissions(value = {"m5141", "m5143"}, logical = Logical.OR)
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean save(@RequestBody OrderInfo orderInfo, @SessionAttribute ShiroUser shiroUser) throws Exception {
//        // 当前管理员是否货运业务岗位
//        if (wmsProperties.getLogistics().getDutyId().get(0).equals(shiroUser.getDutyId()) ||
//                wmsProperties.getLogistics().getDutyId().get(1).equals(shiroUser.getDutyId())) {
//            return ResponseBean.success(logisticsOrderInfoService.saveOrder(orderInfo, shiroUser));
//        }
//        return ResponseBean.error("非法操作");
        return ResponseBean.success(logisticsOrderInfoService.saveOrder(orderInfo, shiroUser));
    }

    @ApiOperation(value = "删除货运单信息")
    @ApiImplicitParam(name = "nos", value = "删除货运单信息id集合", required = true, dataType = "Long", paramType = "query")
    @RequiresPermissions(value = "m5142")
    @RequestMapping(value = "/del", method = RequestMethod.GET)
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean del(@RequestParam(value = "nos") List<Long> ids, @SessionAttribute ShiroUser shiroUser) throws Exception {
        if (CollectionUtils.isEmpty(ids)) {
            return ResponseBean.error("id字符串集不能为空");
        }
        if (ids.size() > 1) {
            return ResponseBean.error("禁止批量操作");
        }
        logisticsOrderInfoService.deleteOrder(ids.get(0), shiroUser);
        return ResponseBean.success();
    }

//    @ApiOperation(value = "货运单审核")
//    @ApiImplicitParam(name = "orderId", value = "货运单信息id", required = true, dataType = "long", paramType = "query")
//    @RequiresPermissions(value = "m5145")
//    @RequestMapping(value = "/audit", method = RequestMethod.POST)
//    @Transactional(rollbackFor = Exception.class)
//    public ResponseBean audit(@RequestBody JSONObject jsonObject, @SessionAttribute ShiroUser shiroUser) throws Exception {
//        Long orderId = jsonObject.getLong("orderId");
//        if (orderId == null) {
//            return ResponseBean.error("参数为空");
//        }
//        logisticsOrderInfoService.audit(orderId, shiroUser);
//        return ResponseBean.success();
//    }

    @ApiOperation(value = "货运单取消")
    @ApiImplicitParam(name = "orderId", value = "货运单信息id", required = true, dataType = "long", paramType = "query")
    @RequiresPermissions(value = "m51491")
    @RequestMapping(value = "/cancel", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean cancel(@RequestBody JSONObject jsonObject, @SessionAttribute ShiroUser shiroUser) throws Exception {
        Long orderId = jsonObject.getLong("orderId");
        String msg = jsonObject.getString("msg");
        if (orderId == null || msg == null) {
            return ResponseBean.error("参数为空");
        }
        logisticsOrderInfoService.cancel(orderId, msg, shiroUser);
        return ResponseBean.success();
    }

    @ApiOperation(value = "货运单发货")
    @ApiImplicitParam(name = "orderId", value = "货运单信息id", required = true, dataType = "long", paramType = "query")
    @RequiresPermissions(value = "m5146")
    @RequestMapping(value = "/shipments", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean shipments(@RequestBody JSONObject jsonObject, @SessionAttribute ShiroUser shiroUser) throws Exception {
        Long orderId = jsonObject.getLong("orderId");
        String credentials = jsonObject.getString("credentials");
        if (orderId == null || credentials == null) {
            return ResponseBean.error("参数为空");
        }
        logisticsOrderInfoService.shipments(orderId, credentials, null, shiroUser);
        return ResponseBean.success();
    }

    @ApiOperation(value = "货运单收货")
    @ApiImplicitParam(name = "orderId", value = "货运单信息id", required = true, dataType = "long", paramType = "query")
    @RequiresPermissions(value = "m5147")
    @RequestMapping(value = "/receiving", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean receiving(@RequestBody JSONObject jsonObject, @SessionAttribute ShiroUser shiroUser) throws Exception {
        Long orderId = jsonObject.getLong("orderId");
        String credentials = jsonObject.getString("credentials");
        if (orderId == null || credentials == null) {
            return ResponseBean.error("参数为空");
        }
        OrderInfo info = logisticsOrderInfoService.receiving(orderId, credentials, shiroUser);
        String[] productIds = info.getProductIds().split(",");
        for (String productId : productIds) {
            kafkaTemplate.send(KafkaTopic.STATISTICS_CAL_PRODCUT, productId, TimeUtil.getTime(new Date()));
        }
        return ResponseBean.success();
    }

    @ApiOperation(value = "货运单定价")
    @ApiImplicitParam(name = "orderId", value = "货运单信息id", required = true, dataType = "long", paramType = "query")
    @RequiresPermissions(value = "m5148")
    @RequestMapping(value = "/pricing", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean pricing(@RequestBody JSONObject jsonObject, @SessionAttribute ShiroUser shiroUser) throws Exception {
        Long orderId = jsonObject.getLong("orderId");
        Long locationId = jsonObject.getLong("locationId");
        BigDecimal price = jsonObject.getBigDecimal("price");
        BigDecimal actualAmount = jsonObject.getBigDecimal("actualAmount");
        String msg = jsonObject.getString("msg");
        if (orderId == null || locationId == null || price == null || actualAmount == null) {
            return ResponseBean.error("参数为空");
        }
        logisticsOrderInfoService.pricing(orderId, locationId, price, actualAmount, msg,jsonObject.getString("pageNo"), shiroUser);
        return ResponseBean.success();
    }

//    @ApiOperation(value = "货运单核算")
//    @ApiImplicitParam(name = "orderId", value = "货运单信息id", required = true, dataType = "long", paramType = "query")
//    @RequiresPermissions(value = "m5149")
//    @RequestMapping(value = "/checkComputation", method = RequestMethod.POST)
//    @Transactional(rollbackFor = Exception.class)
//    public ResponseBean checkComputation(@RequestBody JSONObject jsonObject, @SessionAttribute ShiroUser shiroUser) throws Exception {
//        Long orderId = jsonObject.getLong("orderId");
//        BigDecimal actualAmount = jsonObject.getBigDecimal("actualAmount");
//        if (orderId == null || actualAmount == null) {
//            return ResponseBean.error("参数为空");
//        }
//        logisticsOrderInfoService.checkComputation(orderId, actualAmount, shiroUser);
//        return ResponseBean.success();
//    }

    @ApiOperation(value = "货运单结算")
    @ApiImplicitParam(name = "orderId", value = "货运单信息id", required = true, dataType = "long", paramType = "query")
    @RequiresPermissions(value = "m51492")
    @RequestMapping(value = "/complete", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean complete(@RequestBody JSONObject jsonObject, @SessionAttribute ShiroUser shiroUser) throws Exception {
        Long orderId = jsonObject.getLong("orderId");
        String credentials = jsonObject.getString("credentials");
        if (orderId == null) {
            return ResponseBean.error("参数为空");
        }
        logisticsOrderInfoService.complete(orderId, credentials, shiroUser);
        return ResponseBean.success();
    }

    @ApiOperation(value = "货运单归档")
    @ApiImplicitParam(name = "orderId", value = "货运单信息id", required = true, dataType = "long", paramType = "query")
    @RequiresPermissions(value = "m51494")
    @RequestMapping(value = "/archive", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean archive(@RequestBody JSONObject jsonObject, @SessionAttribute ShiroUser shiroUser) throws Exception {
        Long orderId = jsonObject.getLong("orderId");
        if (orderId == null) {
            return ResponseBean.error("参数为空");
        }
        logisticsOrderInfoService.archive(orderId, shiroUser);
        return ResponseBean.success();
    }

    @ApiOperation(value = "分页查询待结算货运单信息")
    @RequiresPermissions(value = "m5180")
    @RequestMapping(value = "/batch/findBy", method = RequestMethod.POST)
    public ResponseBean findPageBatch(@RequestBody QueryParam<OrderInfoVo> queryParam, @SessionAttribute ShiroUser shiroUser) {
        QueryCondition queryCondition = new QueryCondition();
        queryCondition.setKey("o.status");
        queryCondition.setOper("=");
        queryCondition.setValue(LogisticsConstant.OrderStatus.ALREADY_GATHERING);
        queryParam.getQueryList().add(queryCondition);
        IPage<OrderInfoVo> orderInfoVoIPage = logisticsOrderInfoService.findPage(queryParam);
        return ResponseBean.success(orderInfoVoIPage);
    }

    @ApiOperation(value = "货运单批量结算")
    @ApiImplicitParam(name = "idList", value = "货运单id集合", required = true, dataType = "array", paramType = "query")
    @RequiresPermissions(value = "m5181")
    @RequestMapping(value = "/batch/complete", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean completeBatch(@RequestParam List<Long> idList, @SessionAttribute ShiroUser shiroUser) throws Exception {
        if (!CollectionUtils.isEmpty(idList)) {
            for (Long id : idList) {
                logisticsOrderInfoService.complete(id, null, shiroUser);
            }
            return ResponseBean.success();
        }
        return ResponseBean.error("参数为空");
    }

    @RequiresPermissions(value = "m5182")
    @RequestMapping(value = "/batch/excel-out", method = RequestMethod.POST)
    public ResponseBean excelOut(@RequestBody ExcelParams<OrderCompleteVo, QueryParam<OrderCompleteVo>> excelParams, @SessionAttribute ShiroUser shiroUser) {
        logger.info("===管理员【{}】申请生成运输结算报表Excel===START===", shiroUser.getLoginNo());
        // 组装&调整查询条件
        QueryCondition queryCondition = new QueryCondition();
        queryCondition.setKey("o.status");
        queryCondition.setOper("=");
        queryCondition.setValue(LogisticsConstant.OrderStatus.ALREADY_GATHERING);
        if (CollectionUtils.isEmpty(excelParams.getQueryParam().getQueryList())) {
            excelParams.getQueryParam().setQueryList(new ArrayList<>());
        }
        excelParams.getQueryParam().getQueryList().add(queryCondition);
        PageParam<OrderCompleteVo> pageParam = excelParams.getQueryParam().toPageParam();
        IPage<OrderCompleteVo> page = logisticsOrderInfoMapper.findCompletePage(pageParam.getPage(), pageParam.getEntityWrapper());
        if (page.getRecords().size() == 0) {
            return ResponseBean.error("无已结算运输单！");
        }
        for (OrderCompleteVo orderCompleteVo : page.getRecords()) {
            // 查询发货日期
            List<OrderProcess> orderProcessList = logisticsOrderProcessMapper.findNewest(orderCompleteVo.getId(),
                    LogisticsConstant.OrderStatus.ALREADY_SHIPMENTS, LogisticsConstant.ProcessFlag.NEWEST);
            if (CollectionUtils.isEmpty(orderProcessList)) {
                return ResponseBean.error("数据错误，导出失败！");
            }
            orderCompleteVo.setShipmentsTime(orderProcessList.get(0).getCreateTime());
            // 拼装客户
            orderCompleteVo.setCustomer(orderCompleteVo.getEndArea() + " " + orderCompleteVo.getEndAddress());
            // 设置车源
            orderCompleteVo.setCarType(orderCompleteVo.getId() == 528 ? "外调" : "自营");
        }
        logger.info("===数据量【{}】待生成", page.getTotal());
        ResponseBean responseBean = excelService.create(excelParams.getFileds(), page.getRecords(), OrderCompleteVo.class);
        logger.info("===管理员【{}】申请生成运输结算报表Excel===END===", shiroUser.getLoginNo());
        return responseBean;
    }

    @ApiOperation(value = "货运单驳回")
    @ApiImplicitParam(name = "orderId", value = "货运单信息id", required = true, dataType = "long", paramType = "query")
    @RequiresPermissions(value = "m51493")
    @RequestMapping(value = "/rejected", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public ResponseBean rejected(@RequestBody JSONObject jsonObject, @SessionAttribute ShiroUser shiroUser) throws Exception {
        Long orderId = jsonObject.getLong("orderId");
        String msg = jsonObject.getString("msg");
        if (orderId == null || msg == null) {
            return ResponseBean.error("参数为空");
        }
        logisticsOrderInfoService.rejected(orderId, msg, shiroUser);
        return ResponseBean.success();
    }

    @ApiOperation(value = "根据采购单创建货运单")
    @ApiImplicitParam(name = "supOrderNo", value = "采购单号", required = true, dataType = "string", paramType = "query")
    @RequestMapping(value = "/matchSupOrderInfo", method = RequestMethod.POST)
    public ResponseBean matchSupOrderInfo(String supOrderNo) {
        if (StringUtils.isBlank(supOrderNo)) {
            return ResponseBean.error("参数为空");
        }
        OrderInfo orderInfo = logisticsOrderInfoService.matchSupOrderInfo(supOrderNo);
        return ResponseBean.success(orderInfo);
    }

    @ApiOperation(value = "获取绑定运输单")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(name = "key", value = "模糊查询字段，查询订单号", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "lineType", value = "行驶类型（0-直达车，1-回头车）", required = true, dataType = "String", paramType = "query")
    })
    @RequestMapping(value = "/map/{lineType}/{empId}")
    public ResponseBean map(@RequestParam String key, @PathVariable int lineType, @PathVariable long empId,
                            @SessionAttribute ShiroUser shiroUser) {
        return ResponseBean.success(logisticsOrderInfoService.selectMap(key, empId == 0 ? shiroUser.getId() : empId, lineType));
    }

}
